﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Jacaranda.Data;
using System.Data.Common;

namespace Jacaranda.Model
{
    public class FieldMatchCriteria : ParameterGenerationNode
    {
        public ComparableNode Field { get; set; }

        public BinaryOperator Operator { get; set; }

        public object Value { get; set; }

        public bool IsNegation { get; private set; }


        private int sequence;

        internal override string GenerateSql(Type propertyEntityType)
        {
            string fieldName = Field.GenerateSql(propertyEntityType);

            if (Value == null)
            {
                return string.Format("{0} {1} NULL", fieldName, Operator == BinaryOperator.Equals ? "IS" : "IS NOT");
            }
            else if (Value is SelectMatchCriteria)
            {
                return string.Format("{0} IN ({1})", fieldName, (Value as SelectMatchCriteria).GenerateSql(propertyEntityType));
            }
            else if (Value is ComparableNode)
            {
                return string.Format("{0} {1} {2}", fieldName, OperatorToString(Operator), (Value as ComparableNode).GenerateSql(propertyEntityType));
            }
            else
            {
                string parameterName = "conditionParameter" + ParameterIndex + "_" + sequence++;

                DbParameter parameter = DataAccess.Create().CreateDbParameter();

                parameter.ParameterName = parameterName;

                if (Operator == BinaryOperator.Contains)
                {
                    parameter.Value = "%" + Value + "%";
                }
                else if (Value is Enum)
                {
                    parameter.Value = Value.ToString();
                }
                else
                {
                    parameter.Value = Value;
                }
                
                Command.Parameters.Add(parameter);

                return string.Format("{0} {1} {2}", fieldName, OperatorToString(Operator), DataAccess.Create().CreateParameterizedExpression(parameterName));
            }
        }

        private string OperatorToString(BinaryOperator searchOperator)
        {
            switch (searchOperator)
            {
                case BinaryOperator.Equals:
                    return "=";

                case BinaryOperator.DoesNotEqual:
                    return "<>";

                case BinaryOperator.Contains:
                    return IsNegation ? "NOT LIKE" : "LIKE";

                case BinaryOperator.GreaterThan:
                    return ">";

                case BinaryOperator.GreaterOrEqualThan:
                    return ">=";

                case BinaryOperator.LessThan:
                    return "<";

                case BinaryOperator.LessOrEqualThan:
                    return "<=";

                case BinaryOperator.Addition:
                    return "+";

                case BinaryOperator.Substraction:
                    return "-";

                case BinaryOperator.Multiplication:
                    return "*";

                case BinaryOperator.Division:
                    return "/";

                default:
                    return null;
            }
        }

        public static FieldMatchCriteria operator !(FieldMatchCriteria operand)
        {
            operand.IsNegation = true;
            return operand;
        }
    }
}
